﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Xml.Serialization;

namespace eProject.Model
{

    public class Storage
    {

        public ObservableCollection<Activity> Activities { get; private set; }

        public ObservableCollection<Task> Tasks { get; private set; }

        public ObservableCollection<Employee> Employees { get; private set; }

        public ObservableCollection<ScheduleItem> ScheduleItems { get; private set; }

        public ScheduleSettings ScheduleSettings { get; private set; }

        public Storage()
        {
            Activities = new ObservableCollection<Activity>();
            Tasks = new ObservableCollection<Task>();
            Employees = new ObservableCollection<Employee>();
            ScheduleSettings = new ScheduleSettings();
            ScheduleItems = new ObservableCollection<ScheduleItem>();
        }

        public void Save(Stream stream)
        {
            if (stream == null) throw new ArgumentNullException("stream");

            
            var list = Activities.Select(item => new ActivitySurrogate
                             {
                                 TaskName = item.Task.Name,
                                 Description = item.Description,
                                 EmployeeEMail = item.Employee.Email,
                                 PeriodBegin = item.Period.Begin,
                                 PeriodEnd = item.Period.End,
                                 Priority = item.Priority
                             }).ToList();

            var schItems =
                ScheduleItems.Select(
                    item =>
                    new ScheduleItemSurrogate
                        {
                            EmployeesEmails = new List<string>(item.EmployeesEmails),
                            ManHours = item.ManHours,
                            PeriodBegin = item.Period.Begin,
                            PeriodEnd = item.Period.End
                        }).ToList();
            
            var surrogate = new StorageSurrogate
                                {
                                    Activities = list,
                                    Employees = new List<Employee>(Employees),
                                    Tasks = new List<Task>(Tasks),
                                    ScheduleCommonSettings = ScheduleSettings,
                                    ScheduleItems = schItems
                                };
            var serializer = new XmlSerializer(typeof(StorageSurrogate));
            serializer.Serialize(stream, surrogate);

            
        }

        public void Load(Stream stream)
        {

            if (stream == null) throw new ArgumentNullException("stream");

            var serializer = new XmlSerializer(typeof(StorageSurrogate));
            var mem = (StorageSurrogate)serializer.Deserialize(stream);

            var tasks = mem.Tasks.Select(t => new Task(t.Name, t.Description, t.Duration)).ToList();
            var empls = mem.Employees.Select(e => new Employee(e.Name, e.Surname, e.Email, e.PhoneNumber)).ToList();

            var acts =
                mem.Activities.Select(
                    a => new Activity(tasks.First(t => t.Name == a.TaskName),
                        empls.First(e => e.Email == a.EmployeeEMail), new Period(a.PeriodBegin, a.PeriodEnd), a.Priority, a.Description)).ToList();

            var schItems =
                mem.ScheduleItems.Select(
                    s => new ScheduleItem(new Period(s.PeriodBegin, s.PeriodEnd), s.ManHours, s.EmployeesEmails)).ToList
                    ();

            ScheduleSettings.Load(mem.ScheduleCommonSettings);
            Tasks.Clear();
            Employees.Clear();
            Activities.Clear();
            ScheduleItems.Clear();

            foreach (var item in schItems)
            {
                ScheduleItems.Add(item);
            }
            
            foreach (var empl in empls)
            {
                Employees.Add(empl);
            }
            foreach (var task in tasks)
            {
                Tasks.Add(task);
            }

            foreach (var act in acts)
            {
                Activities.Add(act);
            }

            

        }
        
        [XmlRoot("Memento")]
        public class StorageSurrogate
        {
            [XmlArray("Tasks")]
            [XmlArrayItem("Task")]
            public List<Task> Tasks { get; set; }

            [XmlArray("Employees")]
            [XmlArrayItem("Employee")]
            public List<Employee> Employees { get; set; }

            [XmlArray("Activities")]
            [XmlArrayItem("Activity")]
            public List<ActivitySurrogate> Activities { get; set; }

            [XmlElement("ScheduleCommonSettings")]
            public ScheduleSettings ScheduleCommonSettings{ get; set;}

            [XmlArray("ScheduleItems")]
            [XmlArrayItem("ScheduleItem")]
            public List<ScheduleItemSurrogate> ScheduleItems { get; set; }
        }
   
        [XmlRoot("Activity")]
        public class ActivitySurrogate
        {
            [XmlAttribute]
            public string TaskName { get; set; }

            [XmlAttribute]
            public string EmployeeEMail { get; set; }

            [XmlAttribute]
            public DateTime PeriodBegin { get; set; }

            [XmlAttribute]
            public DateTime PeriodEnd { get; set; }

            [XmlAttribute]
            public int Priority { get; set; }

            [XmlAttribute]
            public string Description { get; set; }   
        }

        [XmlRoot("ScheduleItem")]
        public class ScheduleItemSurrogate
        {
            [XmlElement("EmployeeEmail")]                      
            public List<string> EmployeesEmails { get; set; }

            [XmlAttribute]
            public double ManHours { get; set; }

            [XmlAttribute]
            public DateTime PeriodBegin { get; set; }

            [XmlAttribute]
            public DateTime PeriodEnd { get; set; }
        }
    }

}
